
#include "AbstractKey.h"
#include "../utils/Hash.h"
#include "../utils/StringUtils.h"

/** Set of possible key names for debugging and error messages. */
const char *AbstractKey::key_type_names[] = { "KEY_TYPE_KEY",
                                      "KEY_TYPE_PUBLIC_RSA",
                                      "KEY_TYPE_PRIVATE_RSA",
                                      "KEY_TYPE_PUBLIC_DSA",
                                      "KEY_TYPE_PRIVATE_DSA",
                                      "KEY_TYPE_PUBLIC_ECDSA",
                                      "KEY_TYPE_PRIVATE_ECDSA",
                                      "KEY_TYPE_SYMM_AES" };

/** Set of possible key abbreviations. */
const char *AbstractKey::key_type_abbrs[] = { "key",
                                      "PublicRSA",
                                      "PrivateRSA",
                                      "PublicDSA",
                                      "PrivateDSA",
                                      "PublicECDSA",
                                      "PrivateECDSA",
                                      "SymmAES" };

/** Cryptographic key destructor, destroys 'keyname' string. */
AbstractKey::~AbstractKey()
{
   if (keyname) free((void *)keyname);
   keyname = NULL;
}

/** Get the key type flag, in this case KEY_TYPE_KEY.
 * 
 * @return Return value is Key::KEY_TYPE_KEY. */
const AbstractKey::keytypetype AbstractKey::getKeyType() const
{
   return KEY_TYPE_KEY;
}

/** Get a string description of the key type for debug or error
 * message purposes, usually these are the names of the constant flags
 * denoting key type.
 * 
 * @return Static string reading the full name of the key type. */
const char *AbstractKey::getKeyTypeFullName() const
{
   return key_type_names[getKeyType()];
}

/** Get an abbreviated string descrption of the key type, for the
 * purposes of saving keys to a database labelled with their type.
 * 
 * @return Static string reading the abbreviated name of the key
 * type. */
const char *AbstractKey::getKeyTypeAbbrName() const
{
   return key_type_abbrs[getKeyType()];
}

/** Get the name of the key.
 * 
 * @return Pointer to the internal key name string. */
const char *AbstractKey::getKeyName() const
{
   return keyname;
}

/** Set the name of the key.
 * 
 * @param tname The name to set the internal key name to. */
void AbstractKey::setKeyName(const char *tname)
{
   if (keyname) free((void *)keyname);
   keyname = (tname) ? (const char *)strdup(tname) : NULL;
}

/** Get an MD5 fingerprint of the key. The hexadecimal readable string
 * must be freed by the caller.
 * 
 * @return A human-readable key fingerprint string. */
char *AbstractKey::getMD5KeyFingerprint() const
{
   char *keytextplain = NULL;
   exportKeyToASCII(&keytextplain);
   if (!keytextplain) return NULL;
   char *keyprint = Hash::getHexMD5Hash(keytextplain, strlen(keytextplain), NULL);
   StringUtils::razeString(&keytextplain);
   char *keyprintcolon = Hash::convertToColonHex(keyprint);
   StringUtils::razeString(&keyprint);
   return keyprintcolon;
}

/** Get an SHA1 fingerprint of the key. The hexadecimal readable
 * string must be freed by the caller.
 * 
 * @return A human-readable key fingerprint string. */
char *AbstractKey::getSHA1KeyFingerprint() const
{
   char *keytextplain = NULL;
   exportKeyToASCII(&keytextplain);
   if (!keytextplain) return NULL;
   char *keyprint = Hash::getHexSHA1Hash(keytextplain, strlen(keytextplain), NULL);
   StringUtils::razeString(&keytextplain);
   char *keyprintcolon = Hash::convertToColonHex(keyprint);
   StringUtils::razeString(&keyprint);
   return keyprintcolon;
}

/** Get an SHA256 fingerprint of the key. The hexadecimal readable
 * string must be freed by the caller.
 * 
 * @return A human-readable key fingerprint string. */
char *AbstractKey::getSHA256KeyFingerprint() const
{
   char *keytextplain = NULL;
   exportKeyToASCII(&keytextplain);
   if (!keytextplain) return NULL;
   char *keyprint = Hash::getHexSHA256Hash(keytextplain, strlen(keytextplain), NULL);
   StringUtils::razeString(&keytextplain);
   char *keyprintcolon = Hash::convertToColonHex(keyprint);
   StringUtils::razeString(&keyprint);
   return keyprintcolon;
}

/** Are two abstract keys actually the same (without knowing anything
 * about them?)
 * 
 * @return One if yes, zero if no. */
int AbstractKey::isSameAs(AbstractKey &abskeythat) const
{
   char *abskey_thisd = NULL;
   char *abskey_thatd = NULL;
   exportKeyToASCII(&abskey_thisd);
   abskeythat.exportKeyToASCII(&abskey_thatd);
   if ((abskey_thisd == NULL) || (abskey_thatd == NULL))
   {
      // One of the key failed to exportKeyToASCII
      if (abskey_thisd) free(abskey_thisd);
      if (abskey_thatd) free(abskey_thatd);
      return 0;
   }
   int retval = (strcmp(abskey_thisd, abskey_thatd) == 0);
   if (abskey_thisd) free(abskey_thisd);
   if (abskey_thatd) free(abskey_thatd);
   return retval;
}
